package com.blue.waffle.iwc.utils;

import java.util.LinkedHashMap;

/**
 * A simple java implementation of the LRU cache mechanism.
 * Idea is inspired by Gustavo Steigert 
 * "https://code.google.com/p/steigert-libgdx/source/browse/tags/post-20120314/tyrian-game/src/com/blogspot/steigert/tyrian/utils/LRUCache.java"
 * @author Wenbin
 *
 * @param <K>
 * @param <V>
 */
public class LruCache <K,V> extends LinkedHashMap<K, V>{

	/**
	 * 
	 */
	private static final long serialVersionUID = 7026857165491430848L;

	public static interface OldEntryRemovedListener<K, V>{
		public void notifyOldEntryRemoved(K key, V value);
	}
	
	private OldEntryRemovedListener<K, V> oldEntryRemovedListener;
	
	private int hits;
	private int accessCounts;
	private int maxEntries;
	
	public LruCache(int maxEntries){
		super(maxEntries+1,1.1f,true);
		this.maxEntries=maxEntries;
	}
	
	@Override
	protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
		if (size()>maxEntries) {
			if (oldEntryRemovedListener!=null) {
				oldEntryRemovedListener.notifyOldEntryRemoved(eldest.getKey(), eldest.getValue());
			}
			return true;
		}
		return false;
	}
	
	public int getAccessCounts() {
		return accessCounts;
	}
	
	public int getHits() {
		return hits;
	}
	
	@Override
	public V get(Object key) {
		accessCounts++;
		if (containsKey(key)) {
			hits++;
		}
		return super.get(key);
	}
	
	public void setOldEntryRemovedListener(
			OldEntryRemovedListener<K, V> oldEntryRemovedListener) {
		this.oldEntryRemovedListener = oldEntryRemovedListener;
	}
}
